Skip to main content

Overview

Providers

To operate, the DxChart library requires obtaining data from external sources:

  1. Candle data
  2. List of instruments
  3. Schedule og the instrument trading hours
  4. Quotes
  5. Events about an instrument
  6. News about an instrument
  7. Indicators

To obtain these, the following interfaces have been implemented, whose purpose is to supply data to the library:

  • com.devexperts.dxcharts.provider.DxChartsCandlesProvider - provides data about candles for the selected instrument
  • com.devexperts.dxcharts.provider.DxChartsEventsProvider - provides data about events for the selected instrument (dividends, corporate calendar, splits)
  • com.devexperts.dxcharts.provider.DxChartsIPFProvider - provides data about trading instruments (type, name, exchange time zone)
  • com.devexperts.dxcharts.provider.DxChartsScheduleProvider - provides schedule of the instrument trading hours
  • com.devexperts.dxcharts.provider.DxChartsNewsProvider - provides data about news related to the selected trading instrument
  • com.devexperts.dxcharts.provider.DxChartsQuotesProvider - provides quotes for the selected trading instrument
  • com.devexperts.dxcharts.provider.DxChartsStudiesDataProvider - calculates and provides data about indicators on the chart
  • com.devexperts.dxcharts.provider.DxChartsStudiesPreviewDataProvider - calculates and provides data about the indicator selected for preview during editing

Library users can independently implement interfaces to fetch data from their sources.

All providers interfaces are located in the package com.devexperts.dxcharts.provider.

Passing providers into the library is done using the com.devexperts.dxcharts.provider.DxChartsDataProviders class:

data class DxChartsDataProviders(
val candlesProvider: DxChartsCandlesProvider? = null,
val quotesProvider: DxChartsQuotesProvider? = null,
val ipfProvider: DxChartsIPFProvider? = null,
val scheduleProvider: DxChartsScheduleProvider? = null,
val eventsProvider: DxChartsEventsProvider? = null,
val newsProvider: DxChartsNewsProvider? = null,
val studiesDataProvider: DxChartsStudiesDataProvider? = null,
val studiesDataPreviewProvider: DxChartsStudiesPreviewDataProvider? = null,
)

Which is then passed into com.devexperts.dxcharts.lib.domain.DxChartsConfig and com.devexperts.dxcharts.lib.ui.DxChartsScreen:

//...
val dxChartsDataProviders = DxChartsDataProviders(
/* providers initialization */
)
setContent {
DxChartsTheme(/* Theme params*/ ) {
DxChartsScreen(
dxChartsConfig = DxChartsConfig(
providers = dxChartsDataProviders,
//...
)
)
}
}
//...

By default, all providers are set to null, and no data is received in the library.

Each provider follows a similar template, let's consider the example of DxChartsQuotesProvider:

/**
* Interface for receiving quotes data
*
* When loading dxCharts library chart, quotes data is taken from this interface
*
* When connecting dxCharts library, developer can implement this interface or use the default implementation [com.devexperts.dxcharts.provider.quotes.DxFeedQuotesProvider] and pass it to the library using [DxChartsDataProviders] data class
*
* Use [dataFlow] to get quotes data
*
interface DxChartsQuotesProvider {
/**
* Flow of receiving quotes data
*
* Quotes data is represented by [Quote]
*/
val dataFlow: StateFlow<Quote?>
/**
* Changes quotes' instrument symbol
*
* @param symbol instrument symbol
*/
fun changeSymbol(symbol: String)
}
  • The received data is passed into a StateFlow, to which internal modules of the library subscribe.
  • There is a method for changing the trading instrument symbol to fetch new data.
  • The providers operate asynchronously to the main logic of the library.

Default Providers

For DXfeed clients we already have default implementations of providers that can be easily used for our library.

Default providers:

/**
* [endpointAddress] connects to the dxFeed API at the [endpointAddress].
* [url] parameter is the base URL for accessing the dxFeed API.
* [token] parameter is used for authorization with Base64 encoding.
*/
class DxFeedCandlesProvider(val endpointAddress: String)
class DxFeedQuotesProvider(val endpointAddress: String = "")
class DxFeedNewsProvider(val url: String = "", val token: String = "")
class DxFeedHttpIpfProvider(val url: String = "", val token: String = "")
class DxFeedHttpScheduleProvider(val token: String = "")
class DxFeedEventsProvider(val url: String = "", val token: String = "")
class DxStudiesDataProviderImplementation
class DxStudiesPreviewDataProviderImplementation

DxFeedCandlesProvider and DxFeedQuotesProvider are classes used to connect to the dxFeed data service in order to receive market data such as candle (OHLC) information and quotes. Both DxFeedCandlesProvider and DxFeedQuotesProvider require an endpointAddress parameter, which specifies the address of the dxFeed server or endpoint that these providers will connect to.

DXEndpoint.getInstance().connect(endpointAddress)

DXEndpoint.getInstance(): This retrieves the singleton instance of DXEndpoint, which is responsible for managing the connection to dxFeed services. connect(endpointAddress): This method establishes a network connection to the dxFeed server using the provided endpointAddress

In the DxFeedNewsProvider, DxFeedHttpIpfProvider, and DxFeedEventsProvider classes, the OkHttp library is used to perform HTTP requests in order to retrieve data from a specified url.

private val request = Request.Builder()
.url(url)
.addHeader("Authorization", token)
.build()

.url(url): The .url() method sets the target URL that the HTTP request will be sent to. The url variable is expected to contain a string representing the endpoint from which the data will be retrieved (e.g. https://api.dxfeed.com/news). .addHeader("Authorization", token): The token variable contains the actual token used for authentication or authorization purposes.

Example of how we create an instance of default provider in our demo application:

private val newsProvider = DxFeedNewsProvider(
url = "https://your.url.com/news",
token = "Basic " + String(
Base64.encode(
"your:token".encodeToByteArray(),
Base64.NO_WRAP
)
)
)

DxStudiesDataProviderImplementation and DxStudiesPreviewDataProviderImplementation don't need any parameters. They use dxstudies library under the hood for calculating technical indicators.

Error handling in the default providers

Our default chart providers implement the DxChartsErrorProvider interface, which is designed to streamline error handling in your application. This interface allows you to subscribe to an errorFlow, a reactive stream that notifies you of any errors occurring in the provider.

By subscribing to errorFlow, you can easily monitor and respond to errors in a centralized manner. This setup helps ensure that errors are managed effectively and can be handled appropriately based on your application's needs.

Here’s a detailed overview of how the DxChartsErrorProvider interface works:

  • Error Flow: The errorFlow property provides a StateFlow that emits error events. You will receive updates through this flow whenever an error occurs. If there are no current errors, the flow will emit null, indicating that everything is operating normally.
  • Error Type: The type parameter T in DxChartsErrorProvider must extend ProviderError. This ensures that every error has a descriptive message, which is crucial for understanding the nature of the error and for debugging purposes.
  • ProviderError Interface: This interface defines the structure for errors that include a message and error itself. Implementing ProviderError allows you to attach detailed descriptions to errors, which can be used for logging or displaying informative messages to users.
/**
* Interface for providing a state flow for errors.
*
* This interface defines a contract for providers that need to expose a stream of errors via a [StateFlow].
* Implementations of this interface will provide a [StateFlow] that emits errors of type [T].
*
* The type parameter T should extend ProviderError to ensure that all errors have a message property.
*
* @param T Type of the error. This type must extend [ProviderError] to include a message property.
*/
interface DxChartsErrorProvider<T : ProviderError> {
/**
* A [StateFlow] that emits errors of type [T].
*
* Subscribers to this flow will receive updates whenever an error of type [T] occurs.
* The flow will emit null if there are no current errors, allowing subscribers to handle the absence of errors.
*
* @return A [StateFlow] emitting errors of type [T].
*/
val errorFlow: StateFlow<T?>
}
/**
* Represents an error with an associated message and an optional underlying exception.
*
* Implement this interface to provide errors that include a description and, if available,
* an underlying exception that caused the error. This is useful for logging, debugging, or
* user notifications where additional context about the error is needed.
*/
interface ProviderError {
/**
* A descriptive message about the error.
*
* This message provides context for the error and can be used for both logging purposes
* and informing users about what went wrong.
*
* @return The error message.
*/
val message: String
/**
* An optional underlying exception that caused this error.
*
* If an exception is available, it provides more detailed information about the cause of
* the error. This can be useful for debugging and error handling.
*
* @return The underlying [Exception] if available, or null if there is no additional
* exception information.
*/
val error: Throwable?
}